#include "pthread.h"
#include <stdio.h>

#include "pub.h"
#include <core_api.h>

typedef struct _threadPara {
    // BEST_UINT32 thName; // 0xffffffff
    pthread_t   thID;
    BEST_VOID * thHandle;
    BEST_UINT32 thArgs;
    BEST_BOOL   enable;
} BestThreadPara;

#define BEST_SPEC_MAX_THREAD_SIZE 8

typedef struct _threadPool {
    BestThreadPara pool[BEST_SPEC_MAX_THREAD_SIZE];
    BEST_UINT32    Len;
} BestThreadPool;

BestThreadPool g_BestThreadPool = {0};

BEST_STATUS CORE_ThreadCreate(BEST_VOID *handle, BEST_UINT32 *allocID)
{
    if (g_BestThreadPool.Len >= BEST_SPEC_MAX_THREAD_SIZE) {
        return BEST_ERR;
    }
    if (handle == NULL) {
        return BEST_ERR;
    }
    if (allocID == NULL) {
        return BEST_ERR;
    }
    BEST_INT32 i;
    for (i = 0; i < BEST_SPEC_MAX_THREAD_SIZE; i++) {
        BestThreadPara *para = &g_BestThreadPool.pool[i];
        if (para->enable) {
            continue;
        }
        if (pthread_create(&para->thID, NULL, handle, &para->thArgs) !=
            BEST_OK) {
            printf("Create thread error!\n");
            return BEST_ERR;
        }
        // printf("thread_ret begin.\n");

        // pthread_join(para->thID, NULL);

        // int *thread_ret = NULL;
        // pthread_join(para->thID, (void **)&thread_ret);
        // printf("thread_ret = %d.\n", *thread_ret);
        para->enable   = BEST_TRUE;
        para->thHandle = handle;
        g_BestThreadPool.Len++;
        *allocID = i;
        return BEST_OK;
    }
    printf("pool is full\n");
    return BEST_ERR;
}

BEST_STATUS CORE_ThreadPoolInit()
{
    BEST_INT32 i;
    for (i = 0; i < BEST_SPEC_MAX_THREAD_SIZE; i++) {
        BestThreadPara *para = &g_BestThreadPool.pool[i];
        para->enable         = BEST_FALSE;
        para->thArgs         = 0;
        para->thHandle       = NULL;
        para->thID           = NULL;
    }
    g_BestThreadPool.Len = 0;
    return BEST_OK;
}

BEST_STATUS CORE_ThreadKill(BEST_INT32 allocID)
{
    BEST_INT32 i;
    if (allocID >= BEST_SPEC_MAX_THREAD_SIZE) {
        return BEST_ERR;
    }
    BestThreadPara *para = &g_BestThreadPool.pool[i];
    if (!para->enable) {
        printf("ID %d not work\n", allocID);
        return BEST_ERR;
    }
    printf("will kill this: %d\n", allocID);
    BEST_UINT32 len      = g_BestThreadPool.Len;
    g_BestThreadPool.Len = len > 0 ? len - 1 : 0;
    return BEST_ERR;
}

void *thread(void *arg)
{
    printf("This is a thread and arg = %d.\n", *(int *)arg);
    *(int *)arg = 0;
    return arg;
}

// main func
// int RunDemo(int argc, char *argv[])
int RunDemo()
{
    pthread_t th;
    int       ret;
    int       arg        = 10;
    int *     thread_ret = NULL;
    ret                  = pthread_create(&th, NULL, thread, &arg);
    if (ret != 0) {
        printf("Create thread error!\n");
        return -1;
    }
    printf("This is the main process.\n");
    pthread_join(th, (void **)&thread_ret);
    printf("thread_ret = %d.\n", *thread_ret);
    return 0;
}
